package com.tbit.main.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.tbit.main.dao.core.AccountDao;
import com.tbit.main.dao.core.DetentionMachineBoundMapper;
import com.tbit.main.dao.core.MachineDao;
import com.tbit.main.exception.BaseException;
import com.tbit.main.pojo.*;
import com.tbit.main.pojo.VO.DetentionMachineBoundVO;
import com.tbit.main.service.DetentionMachineBoundService;
import com.tbit.main.service.MachineService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 扣押设备绑定 服务实现类
 * </p>
 *
 * @author chen
 * @since 2023-02-08
 */
@Service
public class DetentionMachineBoundServiceImpl extends ServiceImpl<DetentionMachineBoundMapper, DetentionMachineBound> implements
        DetentionMachineBoundService {

    @Autowired
    private DetentionMachineBoundMapper detentionMachineBoundMapper;
    @Autowired
    private MachineService machineService;
    @Autowired
    private MachineDao machineDao;
    @Autowired
    private AccountDao accountDao;

    @Override
    public List<DetentionMachineBoundVO> getByUserCode(String userCode, Integer accountId) {
        Map<String, Object> map = new HashMap<>();
        Account byAccountId = accountDao.getByAccountId(accountId);
        map.put("userCode", userCode);
        map.put("accountId", accountId);
        List<DetentionMachineBoundVO> list = detentionMachineBoundMapper.getByUserCode(map);
        List<DetentionMachineBoundVO> collect = list.stream().map((detentionMachineBoundVO -> {
            if (detentionMachineBoundVO.getDetentionName() == null || "".equals(detentionMachineBoundVO.getDetentionName())) {
                detentionMachineBoundVO.setDetentionName(byAccountId.getName() + "默认扣押区");
            }
            return detentionMachineBoundVO;
        })).collect(Collectors.toList());
        return collect;
    }


    @Override
    public List<DetentionMachineBoundVO> getByDetentionId(Integer detentionId) {
        Map<String, Object> map = new HashMap<>();
        map.put("detentionId", detentionId);
        List<DetentionMachineBoundVO> list = detentionMachineBoundMapper.getByDetentionId(map);
        return list;
    }

    @Override
    public List<DetentionMachineBoundVO> getByDetentionIdAndUserCode(Integer detentionId,String userCode) {
        Map<String, Object> map = new HashMap<>();
        map.put("detentionId", detentionId);
        if (null != userCode && !"".equals(userCode)){
            map.put("userCode", userCode);
            Machine byUseCode = machineDao.getByUseCode(map);
            if (byUseCode != null){
                map.put("machineId", byUseCode.getMachineId());
            }
        }
        List<DetentionMachineBoundVO> list = detentionMachineBoundMapper.getByDetentionId(map);
        return list;
    }

    @Override
    public String addBatch(String userCodes, Long addTime, String remark,
                           AccountUser accountUser, Integer detentionId,String detentionName,Integer accountId) {


        /**已存在车辆*/
        List<String> userCodeExist = new LinkedList<>();
        /**筛选*/
        List<String> list = Arrays.asList(userCodes.split(","));
        list = list.stream().distinct().collect(Collectors.toList());
        List<Machine> machines = machineService.getByUserCodes(list);

        /**设备权限判断*/
        if (machines.isEmpty()) {
            throw new BaseException("Machine.notExist");
        }
        for (Machine machine : machines) {
            machineService.authCheck(accountUser,machine.getUserCode(),accountId);
        }
        List<Integer> machineId = machines.stream().map(Machine::getMachineId).collect(Collectors.toList());
        QueryWrapper queryWrapper = new QueryWrapper();
        queryWrapper.in("machineId", machineId);
        List<DetentionMachineBound> detentionMachineBoundsDB = list(queryWrapper);
        if (detentionMachineBoundsDB != null && !detentionMachineBoundsDB.isEmpty()) {
            List<Integer> machineIds = detentionMachineBoundsDB.stream().map(DetentionMachineBound::getMachineId).collect(Collectors.toList());

            userCodeExist = machines.stream().filter(a -> machineIds.contains(a.getMachineId())).map(Machine::getUserCode).collect(Collectors.toList());

            machines = machines.stream().filter(a -> !machineIds.contains(a.getMachineId())).collect(Collectors.toList());
        }

        /**不存在车辆*/
        List<String> allList = new ArrayList<>();
        List<String> existNo = new ArrayList<>();
        for (Machine machine : machines) {
            existNo.add(machine.getUserCode());
        }
        allList.addAll(list);
        /**求差集*/
        allList.removeAll(existNo);

        List<DetentionMachineBound> detentionMachineBounds = new ArrayList<>();
        /**循环添加*/
        for (Machine machine : machines) {
            DetentionMachineBound detentionMachineBound = new DetentionMachineBound();
            detentionMachineBound.setAddTime(new Date(addTime));
            detentionMachineBound.setAddTableTime(new Date());
            detentionMachineBound.setAccountId(machine.getAccountId());
            detentionMachineBound.setMachineId(machine.getMachineId());
            detentionMachineBound.setUserId(accountUser.getAccountUserId());
            detentionMachineBound.setDetentionId(detentionId);
            detentionMachineBound.setRemark(remark);
            detentionMachineBound.setDetentionName(detentionName);
            detentionMachineBounds.add(detentionMachineBound);
        }
        if (detentionMachineBounds.size() > 0) {
            saveBatch(detentionMachineBounds);
        }
        if (userCodeExist != null && !userCodeExist.isEmpty()) {
            return userCodeExist + " 已存在扣押车辆";
        }
        if (allList != null && !allList.isEmpty()) {
            return allList + " 车辆不存在";
        }
        return null;
    }

    @Override
    public void del(String userCode, AccountUser accountUser) {
        Machine machine = machineService.getByUseCode(userCode);
        if (machine == null) {
            throw new BaseException("Machine.notExist");
        }
        List<Integer> agentIds = new ArrayList<Integer>();
        for (Agent agent : accountUser.getAgents()) {
            agentIds.add(agent.getAccountId());
        }
        if (!agentIds.contains(machine.getAccountId())) {
            throw new BaseException("System.noPower");
        }
        QueryWrapper queryWrapper = new QueryWrapper();
        queryWrapper.eq("machineId", machine.getMachineId());
        detentionMachineBoundMapper.delete(queryWrapper);
    }

    @Override
    public void delMul(List<String> userCodeS, AccountUser accountUser) {
        List<Machine> machineS = machineService.getByUserCodes(userCodeS);
        for (Machine machine : machineS) {
            if (machine == null) {
                throw new BaseException("Machine.notExist");
            }
            List<Integer> agentIds = new ArrayList<Integer>();
            for (Agent agent : accountUser.getAgents()) {
                agentIds.add(agent.getAccountId());
            }
            if (!agentIds.contains(machine.getAccountId())) {
                throw new BaseException("System.noPower");
            }
            QueryWrapper queryWrapper = new QueryWrapper();
            queryWrapper.eq("machineId", machine.getMachineId());
            detentionMachineBoundMapper.delete(queryWrapper);
        }
    }

    @Override
    public List<DetentionMachineBoundVO> selectByDetentionId(List<Integer> detentionId,String userCode,Integer accountId) {
        Account byAccountId = accountDao.getByAccountId(accountId);
        List<DetentionMachineBoundVO> list = detentionMachineBoundMapper.selectByDetentionId(detentionId, userCode, accountId);
        List<DetentionMachineBoundVO> collect = list.stream().map((detentionMachineBoundVO -> {
            if (detentionMachineBoundVO.getDetentionName() == null || "".equals(detentionMachineBoundVO.getDetentionName())) {
                detentionMachineBoundVO.setDetentionName(byAccountId.getName() + "默认扣押区");
            }
            return detentionMachineBoundVO;
        })).collect(Collectors.toList());
        return collect;

    }

    //批量修改k区
    @Override
    public void updateBatch(List<String> userCodes, AccountUser accountUser,String detentionName,String detentionId) {
        List<Machine> machines = machineService.getByUserCodes(userCodes);

        List<Integer> machineIds = machines.stream().map(Machine::getMachineId).collect(Collectors.toList());
        QueryWrapper queryWrapper = new QueryWrapper();
        queryWrapper.in("machineId", machineIds);
        List<DetentionMachineBound> detentionMachines = list(queryWrapper);
        if (!detentionMachines.isEmpty()) {
            List<Integer> ids = detentionMachines.stream().map(DetentionMachineBound::getBoundId).collect(Collectors.toList());
            UpdateWrapper<DetentionMachineBound> updateWrapper = new UpdateWrapper();
            updateWrapper.in("boundId", ids);
            updateWrapper.set("detentionName", detentionName);
            updateWrapper.set("detentionId", detentionId);
            update(updateWrapper);
        }
    }

    @Override
    public List<DetentionMachineBound> getListByAccount(Integer accountId) {
        return Objects.nonNull(accountId)
                ? detentionMachineBoundMapper.selectList(Wrappers.<DetentionMachineBound>lambdaQuery().eq(DetentionMachineBound::getAccountId, accountId))
                : Collections.emptyList();
    }

    @Override
    public List<Integer> getExist(List<Integer> machineIds) {
        return detentionMachineBoundMapper.getExist(machineIds);
    }

    @Override
    public void deleteBatchByMachineList(List<Integer> machineIdList) {
        LambdaQueryWrapper<DetentionMachineBound> wrapper = new LambdaQueryWrapper<>();
        wrapper.in(DetentionMachineBound::getMachineId, machineIdList);
        detentionMachineBoundMapper.delete(wrapper);
    }
}
